Type.fixTo: Always propagate the naked type to new variants#22852
Type.fixTo: Always propagate the naked type to new variants#22852dlang-bot merged 1 commit intodlang:stablefrom
Conversation
|
Thanks for your pull request, @ibuclaw! Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "stable + dmd#22852" |
|
@kinke - looks reasonable to you? |
|
As the failures suggest, I think this found a bug / typo in one of the |
| t = type.mcache.swcto; // shared wild const -> shared | ||
| else | ||
| t = type.mcache.sto; // shared const => shared | ||
| t = type.mcache.sto; // shared (wild) const => shared |
There was a problem hiding this comment.
Found bug. The swcto back reference of a shared-wild-const type is "naked", not "shared".
It has never been used to hold the reference to the "shared" type, that is in sto instead.
ea600a3 to
59d0ce8
Compare
6066171 to
ea10916
Compare
dkorpel
left a comment
There was a problem hiding this comment.
Man I hate this mcache, well done figuring this out!
Aye, whoever thought it would be a good idea to name all the fields of a struct cto, ito, sto, scto, wto, wcto, swto, and swcto... |
Previously this was only done when the new type was constructed from the main (naked) variant type[1].
However this can result in situations where multiple distinct types are created of the same type.
i.e: Given the
mcachemap.If you call
shared(T).castMod(0), you get the originalT, as the back referenceshared(T).mcache.stoexists.However, if you call
wild-shared(T).castMod(0), then there are two different possible outcomes.When calling
wild-shared(T).mutableOf().unSharedOf(), then we successfully get the originalTvia the back referenceswild-shared(T).mcache.sto.mcache.stoWhen calling
wild-shared(T).unSharedOf().mutableOf()(and this is the case incastMod[2]), then a new variantwild(T)type is constructed and fixed towild-shared(T)only.Then
wild(T).mutableOf()creates a new distinct copy of the originalTbecausewild(T).mcache.wtois null.It's at this point where
Type.merge/merge2should kick in and discard the second copy. But this only succeeds ifT.decowas added into the global type tableType.stringtablebeforecastModwas called !!!If
lookup(T.deco)returns null, then we're stuck with a split-brain situation of two T's floating around the AST.What this patch does is to ensure the mcache map always gets populated with the "naked" type (if constructed) when fixing two variant types together, so the mcache map in the above scenario instead ends up looking like:
So it doesn't matter which variant we have a reference to, we can always get the original "naked" type without having to rely on
merge/merge2.